"""author: wenyao
   data: 2020/10/28
   project: ludingji
"""
#内存溢出： out of memery ,用的太多，给的太少
#内存泄漏： 用完无法释放

#python的内存管理
#引用计数
#垃圾回收
#内存池

#引用计数为主，分代回收和标记清除为辅的内存回收方式

#引用计数
# 每个对象维护一个 ob_ref 字段，用来记录该对象当前被引用的次数
# 每当新的引用指向该对象时，它的引用计数ob_ref加1
# 每当该对象的引用失效时计数ob_ref减1
# 一旦对象的引用计数为0，该对象可以被回收，对象占用的内存空间将被释放。
# 它的缺点是需要额外的空间维护引用计数，这个问题是其次的
# 最主要的问题是它不能解决对象的“循环引用”

#获取对象引用计数
#当使用某个引用作为参数，传递给getrefcount()时，参数实际上创建了一个临时的引用。
# 因此，getrefcount()所得到的结果，会比期望的多1

#增加引用
from sys import getrefcount
a = [1,2,3]
# print(getrefcount(a))
b = a
# print(getrefcount(a))
c = [a,a]
print(getrefcount(a))
print(getrefcount(b))
print(getrefcount(c))

#减少引用
del c[0]
print(c)
b = 2
print(getrefcount(a))

#循环引用 垃圾回收
# >>> x = ["x"]
# >>> y = ["y"]
# >>> x.append(y)
# >>> y.append(x)
# >>> import gc
# >>> print(gc.get_threshold())
# (700, 10, 10)
# >>> gc.collect()
# 0
# >>> del x
# >>> del y
# >>> gc.collect()
# 2

#  三种情况触发垃圾回收
# 调用gc.collect()
# GC达到阀值时
# 程序退出时

#  分代(generation)回收
# 这一策略的基本假设是：存活时间越久的对象，越不可能在后面的程序中变成垃圾。
# Python将所有的对象分为0，1，2三代。
# 所有的新建对象都是0代对象。
# 当某一代对象经历过垃圾回收，依然存活，那么它就被归入下一代对象。
# 垃圾回收启动时，一定会扫描所有的0代对象。
# 如果0代经过一定次数垃圾回收，那么就启动对0代和1代的扫描清理。
# 当1代也经历了一定次数的垃圾回收后，那么会启动对0，1，2，即对所有对象进行扫描。

#标记清除 解决循环引用


#内存池###############
#整数缓冲区 -5-256之间
#字符对象缓冲区（字符串驻留区）
  #数字、字母、下划线组成的这个字符串
  #乘法创建的字符串最多可以驻留20个字符